﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using T.FAS.Runtime.DataAccess.Common;
using T.FAS.Runtime.DataAccess.SPI;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.DataAccess.Engine
{
    class CDOESSQLBuilder: ICDOSQLBuilder
    {        
        /// <summary>
        /// 构造函数
        /// </summary>
        public CDOESSQLBuilder()
        {
            
        }


        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="CompositeDataObject">领域模型</param>        
        /// <param name="dataID">主键数据</param>
        /// <param name="shardingKeyValue">分库分表键值对</param>
        /// <returns>查询SQL</returns>
        public SqlStatementCollection ParseQuerySqlByID(CompositeDataObject CompositeDataObject, string dataID)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            
            var dataIDDic = CreatePkDataDictionary(CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, dataID);
            var dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, DataAccessOpType.Q, dataIDDic);           

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, dataContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, dataContext);

            return sqls;
        }

        private void ParseQuerySqlDetail(SqlStatementCollection sqlSchemata, SqlStatementCollection result, CompositeDataObject CompositeDataObject,
            CompositeNodeObject CompositeNodeObject, DataContext dataContext)
        {
            //构造SQL语句的条件
            var strategy = new ESSelectSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, SQLBuilderUtils.GetCurrentDbType(), dataContext);            
            var rowSqls = new SqlStatementCollection();
            var sqls = sqlSchemata.Where(s => s.SqlBuildingInfo.CurrentNode.ID == CompositeNodeObject.ID).ToList();
            rowSqls.AddRangeClone(sqls);
            strategy.BuildTableSqlDetail(rowSqls, context);
            result.AddRange(rowSqls);
        }

        /// <summary>
        /// 构造查询SQL语句的主干结构
        /// </summary>
        /// <param name="dataObject">数据对象</param>
        /// <returns>查询SQL语句的主干结构</returns>
        private void ParseQuerySqlSchema(SqlStatementCollection sqlSchemata, CompositeDataObject CompositeDataObject, 
            CompositeNodeObject CompositeNodeObject, DataContext dataContext)
        {
            var selectStrategy = new ESSelectSqlBuildStrategy();
            var context = new SqlBuildingContext(CompositeDataObject, CompositeNodeObject, SQLBuilderUtils.GetCurrentDbType(), dataContext);            

            var nodeSqlSchemata = selectStrategy.BuildTableSqlSchema(context);
            sqlSchemata.AddRange(nodeSqlSchemata);
        }

        private Dictionary<string, object> CreatePkDataDictionary(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, string dataID)
        {
            var dataIDDic = new Dictionary<string, object>();
            foreach (var column in CompositeNodeObject.DataObject.PKColumns)
            {
                var pkElement = CompositeNodeObject.Elements.FirstOrDefault(i => i.DataColumnID == column.ID);
                dataIDDic.Add(pkElement.ID, dataID);
                break;
            }
            return dataIDDic;
        }

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="CompositeDataObject">领域模型</param>            
        /// <param name="CompositeNodeObject">领域对象</param>        
        /// <param name="dataID">主键数据</param>
        /// <param name="shardingKeyValue">分库分表键值对</param>
        /// <returns>查询SQL</returns>
        public SqlStatementCollection ParseQuerySqlByID(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, string dataID)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            
            var dataIDDic = CreatePkDataDictionary(CompositeDataObject, CompositeNodeObject, dataID);
            var dataContext = DataContextBuilder.CreateDataContext<IDictionary<string, object>>(CompositeDataObject, CompositeNodeObject, DataAccessOpType.Q, dataIDDic);            

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, CompositeDataObject, CompositeNodeObject, dataContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, CompositeDataObject, CompositeNodeObject, dataContext);

            return sqls;
        }

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <param name="CompositeDataObject">领域模型</param>        
        /// <param name="filter">过滤器</param>
        /// <returns>查询SQL</returns>
        public SqlStatementCollection ParseQuerySqlByFilter(CompositeDataObject CompositeDataObject, QueryFilter filter, SqlExecuteControlContext controlContext = null)
        {
            return ParseQuerySqlByFilter(CompositeDataObject, CompositeDataObject.RootCompositeNodeObject, filter);
        }

        /// <summary>
        /// 解析生成查询SQL
        /// </summary>
        /// <remarks>按主键数据作为查询依据</remarks>
        /// <param name="CompositeDataObject">领域模型</param>            
        /// <param name="CompositeNodeObject">领域对象</param>               
        /// <param name="filter">过滤器</param>
        /// <returns>查询SQL</returns>
        public SqlStatementCollection ParseQuerySqlByFilter(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, QueryFilter filter, SqlExecuteControlContext controlContext = null)
        {
            var sqls = new SqlStatementCollection();
            var sqlSchema = new SqlStatementCollection();
            
            var dataContext = DataContextBuilder.CreateDataContext<QueryFilter>(CompositeDataObject, CompositeNodeObject, DataAccessOpType.Q, filter);            

            //解析SQL语句主干接口
            ParseQuerySqlSchema(sqlSchema, CompositeDataObject, CompositeNodeObject, dataContext);

            //在SqlSchema上逐表添加数据
            ParseQuerySqlDetail(sqlSchema, sqls, CompositeDataObject, CompositeNodeObject, dataContext);

            return sqls;
        }

        public SqlStatementCollection ParseInsertSql(CompositeDataObject CompositeDataObject, TRecord instance, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseInsertSql(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, TRecord instance, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseQuerySqlByID(CompositeDataObject CompositeDataObject, string dataID, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseQuerySqlByID(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, string dataID, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseDeleteSqlByID(CompositeDataObject CompositeDataObject, string dataID, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseDeleteSqlByID(CompositeDataObject CompositeDataObject, CompositeNodeObject CompositeNodeObject, string dataID, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseUpdateSql(CompositeDataObject CompositeDataObject, TRecord data, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }

        public SqlStatementCollection ParseUpdateSql(CompositeDataObject CompositeDataObject, CompositeNodeObject momainObject, TRecord data, SqlExecuteControlContext context = null)
        {
            throw new NotImplementedException();
        }
    }
}
